From: Ray Strode Date: Mon, 11 Mar 2013 16:31:52 +0000 (-0400) Subject: recorder: port to XInput2 X-Git-Tag: archive/raspbian/50.5-1+rpi1~1^2~1013^2^2~4504 X-Git-Url: https://dgit.raspbian.org/%22http://www.example.com/cgi/%22/%22http:/www.example.com/cgi/%22?a=commitdiff_plain;h=ddced7947558d50006d1c17891fe5af33c2c40de;p=gnome-shell.git recorder: port to XInput2 Pointer tracking is broken when the pointer is over the stage input area. This is apparently fallout from mutter going to XInput2. This commit changes the mouse event handling code to also use XInput2. https://bugzilla.gnome.org/show_bug.cgi?id=695324 --- diff --git a/src/shell-recorder.c b/src/shell-recorder.c index f2bd68639..2e9ec4ae7 100644 --- a/src/shell-recorder.c +++ b/src/shell-recorder.c @@ -19,6 +19,11 @@ #include #include +#include +#include + +/* This is also hard-coded in mutter and GDK */ +#define VIRTUAL_CORE_POINTER_ID 2 typedef enum { RECORDER_STATE_CLOSED, @@ -57,6 +62,8 @@ struct _ShellRecorder { gboolean have_xfixes; int xfixes_event_base; + int xinput_opcode; + CoglHandle recording_icon; /* icon shown while playing */ cairo_surface_t *cursor_image; @@ -661,10 +668,15 @@ recorder_event_filter (XEvent *xev, gpointer data) { ShellRecorder *recorder = data; + XIEvent *input_event = NULL; if (xev->xany.window != clutter_x11_get_stage_window (recorder->stage)) return CLUTTER_X11_FILTER_CONTINUE; + if (xev->xany.type == GenericEvent && + xev->xcookie.extension == recorder->xinput_opcode) + input_event = (XIEvent *) xev->xcookie.data; + if (xev->xany.type == recorder->xfixes_event_base + XFixesCursorNotify) { XFixesCursorNotifyEvent *notify_event = (XFixesCursorNotifyEvent *)xev; @@ -680,36 +692,53 @@ recorder_event_filter (XEvent *xev, recorder_queue_redraw (recorder); } } - else if (xev->xany.type == MotionNotify) + else if (input_event != NULL && + input_event->evtype == XI_Motion) { - recorder->pointer_x = xev->xmotion.x; - recorder->pointer_y = xev->xmotion.y; + XIDeviceEvent *device_event = (XIDeviceEvent *) input_event; + if (device_event->deviceid == VIRTUAL_CORE_POINTER_ID) + { + recorder->pointer_x = device_event->event_x; + recorder->pointer_y = device_event->event_y; - recorder_queue_redraw (recorder); + recorder_queue_redraw (recorder); + } } /* We want to track whether the pointer is over the stage * window itself, and not in a child window. A "virtual" * crossing is one that goes directly from ancestor to child. */ - else if (xev->xany.type == EnterNotify && - (xev->xcrossing.detail != NotifyVirtual && - xev->xcrossing.detail != NotifyNonlinearVirtual)) + else if (input_event != NULL && + input_event->evtype == XI_Enter) { - recorder->have_pointer = TRUE; - recorder->pointer_x = xev->xcrossing.x; - recorder->pointer_y = xev->xcrossing.y; + XIEnterEvent *enter_event = (XIEnterEvent *) input_event; - recorder_queue_redraw (recorder); + if (enter_event->deviceid == VIRTUAL_CORE_POINTER_ID && + (enter_event->detail != XINotifyVirtual && + enter_event->detail != XINotifyNonlinearVirtual)) + { + recorder->have_pointer = TRUE; + recorder->pointer_x = enter_event->event_x; + recorder->pointer_y = enter_event->event_y; + + recorder_queue_redraw (recorder); + } } - else if (xev->xany.type == LeaveNotify && - (xev->xcrossing.detail != NotifyVirtual && - xev->xcrossing.detail != NotifyNonlinearVirtual)) + else if (input_event != NULL && + input_event->evtype == XI_Leave) { - recorder->have_pointer = FALSE; - recorder->pointer_x = xev->xcrossing.x; - recorder->pointer_y = xev->xcrossing.y; + XILeaveEvent *leave_event = (XILeaveEvent *) input_event; + + if (leave_event->deviceid == VIRTUAL_CORE_POINTER_ID && + (leave_event->detail != XINotifyVirtual && + leave_event->detail != XINotifyNonlinearVirtual)) + { + recorder->have_pointer = FALSE; + recorder->pointer_x = leave_event->event_x; + recorder->pointer_y = leave_event->event_y; - recorder_queue_redraw (recorder); + recorder_queue_redraw (recorder); + } } return CLUTTER_X11_FILTER_CONTINUE; @@ -862,7 +891,8 @@ recorder_set_stage (ShellRecorder *recorder, if (recorder->stage) { - int error_base; + int error_base, event_base; + int major = 2, minor = 3; recorder->stage = stage; g_signal_connect (recorder->stage, "destroy", @@ -886,6 +916,28 @@ recorder_set_stage (ShellRecorder *recorder, clutter_x11_get_stage_window (stage), XFixesDisplayCursorNotifyMask); + if (XQueryExtension (clutter_x11_get_default_display (), + "XInputExtension", + &recorder->xinput_opcode, + &error_base, + &event_base)) + { + if (XIQueryVersion (clutter_x11_get_default_display (), &major, &minor) == Success) + { + int version = (major * 10) + minor; + if (version < 22) + g_warning("ShellRecorder: xinput version %d.%d is too old", major, minor); + } + else + { + g_warning("ShellRecorder: xinput version could not be queried"); + } + } + else + { + g_warning("ShellRecorder: xinput extension unavailable"); + } + clutter_stage_ensure_current (stage); recorder_get_initial_cursor_position (recorder);